package com.coalmine.activiti.flow.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.coalmine.activiti.api.dto.ApprovalDTO;
import com.coalmine.activiti.api.dto.FlowMessageDTO;
import com.coalmine.activiti.common.core.annotation.DisableDataFilter;
import com.coalmine.activiti.common.flow.constant.FlowApprovalType;
import com.coalmine.activiti.common.flow.constant.FlowConstant;
import com.coalmine.activiti.common.flow.constant.FlowTaskStatus;
import com.coalmine.activiti.common.flow.model.FlowEntry;
import com.coalmine.activiti.common.flow.model.FlowEntryPublish;
import com.coalmine.activiti.common.flow.model.FlowTaskComment;
import com.coalmine.activiti.common.flow.service.FlowEntryService;
import com.coalmine.activiti.flow.constant.CmFlowConstant;
import com.coalmine.activiti.flow.service.CmFlowApiService;
import com.coalmine.activiti.flow.service.CmFlowService;
import com.coalmine.activiti.webadmin.upms.service.IActDeBusinessService;
import com.coalmine.common.core.domain.R;
import com.coalmine.common.core.utils.SecurityUtils;
import com.coalmine.common.core.utils.StringUtils;
import com.coalmine.common.mq.config.KafkaTopicConfig;
import com.coalmine.common.mq.manager.KafkaProducerManager;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;

@Slf4j
@RestController
public class RejectFlowController {

    @Autowired
    private IActDeBusinessService actDeBusinessService;
    @Autowired
    private CmFlowApiService cmFlowApiService;
    @Autowired
    private CmFlowService cmFlowService;
    @Autowired
    private FlowEntryService flowEntryService;
    @Autowired
    private KafkaProducerManager kafkaProducerManager;

    /**
     * 驳回
     *
     * @param approvalDTO 审批对象（同意|驳回）
     * @return
     */
    @DisableDataFilter
    @PostMapping(path = "/rejectFlow")
    public R<Boolean> rejectFlow(@RequestBody ApprovalDTO approvalDTO) {
        log.info("开始驳回任务======================================");
        log.info("审批对象: {}, 审批类型: {}", JSON.toJSONString(approvalDTO), FlowApprovalType.REJECT);

        long beginTime = System.currentTimeMillis();
        String errorMessage;
        JSONObject taskVariableData = new JSONObject();
        String loginName = SecurityUtils.getUsername();

        // 获取流程标识Key
        String processDefinitionKey=null;
        //校验查询类型
        /*if (StrUtil.isBlank(approvalDTO.getQueryType())) {
            errorMessage = "数据验证失败，查询类型[queryType]为空！";
            log.info(errorMessage);
            return R.fail(false, errorMessage);
        }*/
        if (StrUtil.isNotBlank(approvalDTO.getProcessKey())) {

            //FlowEntry flowEntry = flowEntryService.getFlowEntryByProcessDefinitionKey(approvalDTO.getProcessKey());
            //FlowEntryPublish flowEntryPublish = flowEntryService.getFlowEntryPublishByEntryId(flowEntry.getEntryId());
            processDefinitionKey = approvalDTO.getProcessKey();

        }else{
            taskVariableData.put("tableName", approvalDTO.getTableName());
            taskVariableData.put("dataId", approvalDTO.getBizId());
            taskVariableData.put("type", approvalDTO.getType());
            // 获取流程标识Key
            processDefinitionKey = actDeBusinessService.findDefinitionKeyByTableName(approvalDTO.getTableName(), approvalDTO.getType());
        }
        if (StringUtils.isEmpty(processDefinitionKey)) {
            errorMessage = "processDefinitionKey为空，不能启动新流程！";
            log.info(errorMessage);
            return R.fail(false, errorMessage);
        }
        //流程模板对象
        FlowEntry flowEntry = flowEntryService.getFlowEntryByProcessDefinitionKey(processDefinitionKey);

        // 获取流程任务列表
        List<Task> taskList = cmFlowApiService.getTaskListByUserNameAndDataId(loginName, processDefinitionKey, approvalDTO.getBizId());
        if (CollectionUtils.isEmpty(taskList)) {
            errorMessage = "数据验证失败，流程任务列表为空！";
            log.info(errorMessage);
            return R.fail(false, errorMessage);
        }

        // 获取流程任务
        Task task = taskList.get(0);
        if (null == task) {
            errorMessage = "数据验证失败，流程任务为空！";
            log.info(errorMessage);
            return R.fail(false, errorMessage);
        }

        // 获取流程变量
        int nextNodeIndex = (int) cmFlowApiService.getTaskVariable(task.getId(), CmFlowConstant.NEXT_NODE_INDEX);
        //审批人
        List<String> approverList = (List<String>) cmFlowApiService.getTaskVariable(task.getId(), CmFlowConstant.GROUP_TYPE_BUSINESS_APPROVAL_USER_VAR);
        if (CollectionUtils.isEmpty(approverList)) {
            errorMessage = "数据验证失败，审批人列表为空！";
            log.info(errorMessage);
            return R.fail(false, errorMessage);
        }

        // 验证登录用户是否为该待办任务当前节点审批人
        //会签改造
        if (!approverList.get(nextNodeIndex).contains(loginName)) {
        //if (!StrUtil.equals(loginName, approverList.get(nextNodeIndex))) {
            errorMessage = "数据验证失败，登录用户不是该待办任务当前节点审批人！";
            log.info(errorMessage);
            return R.fail(false, errorMessage);
        }

        // 设置流程任务批注
        FlowTaskComment flowTaskComment = new FlowTaskComment();
        flowTaskComment.setApprovalType(FlowApprovalType.REJECT);
        flowTaskComment.setComment(approvalDTO.getComment());

        if (0 == nextNodeIndex) {
            errorMessage = "数据验证失败，流程的发起人不能驳回该任务！";
            log.info(errorMessage);
            return R.fail(false, errorMessage);
        }

        // 保存业务数据到流程变量中
        taskVariableData.put(CmFlowConstant.NEXT_NODE_INDEX, nextNodeIndex - 1);
        taskVariableData.put(CmFlowConstant.NEXT_NODE_APPROVER, approverList.get(nextNodeIndex - 1));
        taskVariableData.put(CmFlowConstant.GROUP_TYPE_BUSINESS_APPROVAL_USER_VAR, approverList);

        //保存动态流程变量
        if(approvalDTO.getConditions()!=null){
            approvalDTO.getConditions().stream().forEach(a ->{
                taskVariableData.put(a.getKey(),a.getValue());
            });
        }
        //会签判断
        List assigneeList = (List) cmFlowApiService.getTaskVariable(task.getId(), FlowConstant.MULTI_ASSIGNEE_LIST_VAR);
        if (!CollectionUtils.isEmpty(assigneeList)) {
        	flowTaskComment.setApprovalType(FlowApprovalType.MULTI_REFUSE);
		}

        // 更新流程状态，同时接收流程任务。
        cmFlowService.updateAndTakeTask(
                task,
                flowTaskComment,
                taskVariableData,
                approvalDTO.getBizId(),
                FlowTaskStatus.REFUSED);

        // 组装流程消息对象
        FlowMessageDTO flowMessageDTO = new FlowMessageDTO();
        flowMessageDTO.setBizType(approvalDTO.getType());
        flowMessageDTO.setBizId(approvalDTO.getBizId());
        flowMessageDTO.setAction(FlowApprovalType.REJECT);
        flowMessageDTO.setApprover(loginName);
        flowMessageDTO.setProcessKey(processDefinitionKey);
        flowMessageDTO.setProcessKey(flowEntry.getProcessDefinitionName());
        flowMessageDTO.setApproveTime(new Date());
        flowMessageDTO.setResult(true);

        // 通过消息推送方式驱动业务状态流转
        kafkaProducerManager.sendMessageSync(KafkaTopicConfig.flowTopic, JSON.toJSONString(flowMessageDTO));

        log.info("流程消息对象: {}", JSON.toJSONString(flowMessageDTO));
        log.info("驳回任务耗时: {} ms", (System.currentTimeMillis() - beginTime));
        return R.ok(true, CmFlowConstant.RESULT_SUCCESS);
    }

}
